﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.IO;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Linq;

namespace HighFantasy
{
    public class Player
    {
        // Animations
        public Texture2D Rectangular, Face;
        private Animation leftAnimation;
        private Animation rightAnimation;
        private Animation downAnimation;
        private Animation upAnimation;
        private Animation IdleLeft, IdleRight, IdleDown, IdleUp;
        private AnimationPlayer sprite;
        private SpriteEffects flip;
        public int direction, CoordX, CoordY, levelid;
        public Collision collision;
        public PlayerData data;
        public Stream datastream;

        public Level Level
        {
            get { return level; }
        }
        Level level;

        public int X, Y, Width, Height;
        public float movement;

        // Physics state
        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }
        Vector2 position;

        public Vector2 Velocity
        {
            get { return velocity; }
            set { velocity = value; }
        }
        Vector2 velocity;

        private Rectangle localBounds;
        /// <summary>
        /// Gets a rectangle which bounds this player in world space.
        /// </summary>
        public Rectangle BoundingRectangle
        {
            get
            {

                return localBounds;
            }
        }
        
      
        public Player(Level level, int X, int Y)
        {
            this.level = level;
            this.X = X * 32;
            this.Y = Y * 32;
            this.Width = 64;
            this.Height = 64;
            this.CoordX = X;
            this.CoordY = Y;
            this.collision = new Collision();
            Position = new Vector2(this.X , this.Y);

            string path = "Content/Data/" + "PlayerData.xml";
            #if ANDROID ||  WINDOWS_PHONE

            XDocument doc;
            using (Stream stream = TitleContainer.OpenStream(path))
            {
                doc = XDocument.Load(stream);
            }
            #endif

         

            LoadContent();



        }

        public void LoadContent()
        {
            // Load animated textures.
            Face = Level.Content.Load<Texture2D>("Background/" + data.Profile.Face + "_face");

            IdleRight = new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Idle_right"), 0.5f, true, 1);
            IdleLeft= new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Idle_right"), 0.5f, true, 1);
            IdleDown = new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Idle_right"), 0.5f, true, 1);
            IdleUp = new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Idle_right"), 0.5f, true, 1);
            leftAnimation = new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Player_left"), 0.2f, true, 3);
            rightAnimation = new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Player_right"), 0.2f, true, 3);
            downAnimation = new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Player_down"), 0.2f, true, 3);
            upAnimation = new Animation(Level.Content.Load<Texture2D>("Sprites/Player/Player_up"), 0.2f, true, 3);
            Rectangular = Level.Content.Load<Texture2D>("Background/Player_rect");
            
          
            localBounds = new Rectangle(X, Y, Width, Height);

            
            Velocity = Vector2.Zero;
            sprite.PlayAnimation(IdleRight);

        }

        public void Update(GameTime gameTime, KeyboardState keyboardState)
        {

            

         if (keyboardState.IsKeyDown(Keys.Left))       
         {
             direction = 1;

             if (!HandleTileCollisions(1) && !collision.PlayerCollisionRight(this, level.objects, level.enemies))
             {
               sprite.PlayAnimation(leftAnimation);
               movement = -1.0f;
               X += (int)movement;
               velocity.X += movement;
              
               
             }
             else
             {
                 sprite.PlayAnimation(IdleLeft);
                 movement = 0f;

             }

         }

         else if (keyboardState.IsKeyDown(Keys.Right))
        {
            direction = 2;
            if (!HandleTileCollisions(2) && !collision.PlayerCollisionLeft(this, level.objects, level.enemies))
            {
            
            sprite.PlayAnimation(rightAnimation);
            movement = 1.0f;
            X += (int)movement;
            velocity.X += movement;
            
            
            }

            else
            {
                sprite.PlayAnimation(IdleRight);
                movement = 0f;

            }
        }
         else if (keyboardState.IsKeyDown(Keys.Up))
         {
             direction = 3;
             if (!HandleTileCollisions(3) && !collision.PlayerCollisionBottom(this, level.objects, level.enemies))
            {

             sprite.PlayAnimation(upAnimation);
             movement = -1.0f;
             Y += (int)movement;
             velocity.Y += movement;
             

            }

             else
             {
                 sprite.PlayAnimation(IdleUp);
                 movement = 0f;

             }
         }
         else if (keyboardState.IsKeyDown(Keys.Down))
         {
             direction = 4;
             if (!HandleTileCollisions(4) && !collision.PlayerCollisionTop(this, level.objects, level.enemies))
            {
             sprite.PlayAnimation(downAnimation);
             movement = 1.0f;
             Y += (int)movement;
             velocity.Y += movement;
             

            }

             else
             {
                 sprite.PlayAnimation(IdleDown);
                 movement = 0f;

             }
         }
         else if (keyboardState.IsKeyDown(Keys.A))
         {
             level.Exitreached = true;
             levelid += 1;
         }
         else if (keyboardState.IsKeyDown(Keys.Escape))
         {

             if (level.panelarea.isVisible == false)
             level.panelarea.isVisible = true;
             else
             level.panelarea.isVisible = false;
         }

        ApplyPhysics(gameTime);
        

        }

        public void ApplyPhysics(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;


            Vector2 previousPosition = Position;
            this.CoordX = (int)position.X / 32;
            this.CoordY = (int)position.Y / 32;
            position = new Vector2(X, Y);
            Position = position;

            

        }

        public void LoadLevel(int id)
        {
            // move to the next level id
            string path = level.Content.RootDirectory + "/Maps/";

            Stream stream = File.Open(path + id + ".xml", FileMode.Open);
            StreamReader txtreader = new StreamReader(stream);

            level = new Level(id.ToString(), stream, id, level.Content);
        }

        private bool HandleTileCollisions(int direction)
        {
                        
           
             switch (direction)
                 {

                 case 1:

                     
            
                    // If this tile is collidable,
                    TileCollision collision = Level.GetCollision(CoordX - 1, CoordY);
                    if (collision == TileCollision.Impassable)
                    {
                        
                            // Resolve the collision along the X axis.
                           Position = new Vector2(Position.X, Position.Y);
                           return true;
                        
                    }
                    else if (collision == TileCollision.Exit)
                     {
                         level.Exitreached = true;
                         return false;
                     }

                    break;

                 case 2:

                    
                  TileCollision collision2 = Level.GetCollision(CoordX + 1, CoordY);
                  if (collision2 == TileCollision.Impassable)
                    {
                        
                            // Resolve the collision along the X axis.
                           Position = new Vector2(Position.X, Position.Y);
                           return true;
                        
                    }
                  else if (collision2 == TileCollision.Exit)
                  {

                      level.Exitreached = true;
                      return false;
                  }

                    break;

                 case 3:


                    TileCollision collision3 = Level.GetCollision(CoordX, CoordY - 1);
                    if (collision3 == TileCollision.Impassable)
                    {

                        // Resolve the collision along the X axis.
                        Position = new Vector2(Position.X, Position.Y);
                        return true;

                    }
                    else if (collision3 == TileCollision.Exit)
                    {

                        level.Exitreached = true;
                        return false;
                    }

                    break;

                 case 4:


                    TileCollision collision4 = Level.GetCollision(CoordX, CoordY + 1);
                    if (collision4 == TileCollision.Impassable)
                    {

                        // Resolve the collision along the X axis.
                        Position = new Vector2(Position.X, Position.Y);
                        return true;

                    }
                    else if (collision4 == TileCollision.Exit)
                    {
                        level.Exitreached = true;
                        return false;

                    }

                    break;

                 }

            
            return false;

        }

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            // Flip the sprite to face the way we are moving.
            if (Velocity.X > 0)
                flip = SpriteEffects.None;
            

            // Draw that sprite.
            sprite.Draw(gameTime, spriteBatch, Position, flip);
            spriteBatch.Draw(Rectangular, Position, Color.White);
        }
    }
}
